package com.flow.framework.web.filter;

import com.flow.framework.base.service.system.ops.ISystemOpsSecurityService;
import com.flow.framework.common.error.SystemErrorCode;
import com.flow.framework.common.exception.CheckedException;
import com.flow.framework.common.util.verify.VerifyUtil;
import com.flow.framework.web.util.HttpServletUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.context.config.annotation.RefreshScope;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * 运维敏感操作过滤器，该过滤器主要作用是对运维敏感操作进行鉴权，该过滤器执行的顺序在web全局过滤器之后，
 * 原因是可能敏感操作需要记录入访日志（可使用配置文件进行控制），参考com.flow.framework.base.properties.component.RequestConfigProperties#ignoreRecordTraceUris
 *
 * @author luoguopiao
 * @version 0.0.1
 * @date 2022/12/25
 */
@WebFilter(urlPatterns = "/*")
@Slf4j
@RefreshScope
@RequiredArgsConstructor
public class SystemOpsSecurityFilter implements Filter {

    private final ISystemOpsSecurityService systemOpsSecurityService;

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
        String uri = httpServletRequest.getRequestURI();
        String method = httpServletRequest.getMethod();
        if (VerifyUtil.isEmpty(method)) {
            log.error("unauthorized error, method is null. uri: {}", uri);
            throw new CheckedException(SystemErrorCode.UNAUTHORIZED_ERROR);
        }
        Map<String, List<String>> allHeaders = HttpServletUtil.getAllHeaders(httpServletRequest);

        // 如果请求uri和请求方法匹配，则需要进行权限校验
        if (systemOpsSecurityService.isUriMatch(httpServletRequest.getContextPath(), method, uri)
                && !systemOpsSecurityService.authentication(allHeaders)) {
            log.error("unauthorized error. uri: {}", uri);
            throw new CheckedException(SystemErrorCode.UNAUTHORIZED_ERROR);
        }
        filterChain.doFilter(httpServletRequest, httpServletResponse);
    }
}